import type { RouteRecordRaw } from 'vue-router';
import { shallowRef } from 'vue';
import type { DefineComponent } from 'vue';
import ErrorBound from '@/pages/Base/Error/index.vue';
import SubLayout from '@/components/layout/index.vue';
import { cloneDeep } from 'lodash-es';
const modules = import.meta.glob('@/pages/**/*.vue');
const __import = (src?: string, name?: string) => async () => {
  try {
    if (!src) return await Promise.resolve(ErrorBound);
    const comp = await (
      modules[`/src/pages/${src}.vue`] as () => Promise<DefineComponent>
    )();
    // 加入name 用于keep-alive
    if (name && name !== '') comp.default.name = name;
    return await Promise.resolve(comp.default);
  } catch (error) {
    console.log(error);
    return await Promise.resolve(ErrorBound);
  }
};

export type MenuInfoWidthChildren = MenuInfo & {
  children?: MenuInfoWidthChildren[];
};

/**
 * @description: 菜单转路由
 * @param {MenuInfo[]} menus
 * @returns {MenuInfoWidthChildren[]}
 */
const convertRouteTree = (
  menus: MenuInfo[]
): { keepAlives: string[]; configs: MenuInfoWidthChildren[] } => {
  //根据菜单生成路由

  const keepAlives: string[] = [];

  const list = cloneDeep(menus);

  let result: MenuInfoWidthChildren[] = [];

  const map = list.reduce<{ [key: string]: MenuInfoWidthChildren }>(
    (res, v) => ((res[v.menuId] = v), res),
    {}
  );

  for (const item of list) {
    if (item.keepAlive) keepAlives.push(`viewId:${item.menuId}`);
    if (item.parentId) {
      const parent = map[item.parentId];
      (parent.children || (parent.children = [])).push(item);
      parent.children.sort(
        ({ showOrder: aShow = 1 }, { showOrder: bShow = 1 }) => aShow - bShow
      );
    } else {
      result.push(item);
      result = result.sort(
        ({ showOrder: aShow = 1 }, { showOrder: bShow = 1 }) => aShow - bShow
      );
    }
  }

  return { configs: result, keepAlives };
};

/**
 * @description: 生成路由
 * @param {MenuInfoWidthChildren[]} config
 * @returns {RouteRecordRaw[]}
 */
const genRouteByConfig = (
  config: MenuInfoWidthChildren[],
  isLayout = false
): RouteRecordRaw[] => {
  const routes: RouteRecordRaw[] = [];
  for (const item of config) {
    if (!isLayout || item.isAlone) {
      const routeItem: RouteRecordRaw = {
        path: `${item.routePath}`,
        meta: {
          title: item.menuName,
          icon: item.icon,
          group: item.group,
          hidden: item.isHidden,
          redirect: item.redirect,
          full: item.isAlone
        },
        name: `viewId:${item.menuId}`,
        component: __import(item.src, `viewId:${item.menuId}`)
      };
      if (item.children?.length) {
        // 路由升维
        genRouteByConfig(item.children).forEach((v) => routes.push(v));
      }
      routes.push(routeItem);
    } else {
      if (item.children?.length) {
        routes.push({
          path: `${item.routePath}`,
          meta: {
            title: item.menuName,
            icon: item.icon,
            group: item.group,
            hideChild: false
          },
          component: shallowRef(SubLayout),
          redirect: `${genRouteByConfig(item.children)[0].path}`,
          children: genRouteByConfig(item.children)
        });
      } else {
        routes.push({
          path: `/root-${item.menuId}`,
          meta: {
            title: item.menuName,
            icon: item.icon,
            group: item.group,
            hidden: item.isHidden,
            redirect: item.redirect,
            hideChild: true
          },
          component: shallowRef(SubLayout),
          redirect: `${item.routePath}`,
          children: [
            {
              path: `${item.routePath}`,
              name: `viewId:${item.menuId}`,
              meta: {
                title: item.menuName,
                icon: item.icon,
                group: item.group,
                hidden: item.isHidden,
                redirect: item.redirect
              },
              component: __import(item.src, `viewId:${item.menuId}`)
            }
          ]
        });
      }
    }
  }

  return routes;
};

/**
 * @description: 菜单转路由
 * @param {MenuInfo[]} menus
 * @returns {RouteRecordRaw[]}
 */
const genRoutes = (
  menus: MenuInfo[]
): {
  routes: RouteRecordRaw[];
  configs: MenuInfoWidthChildren[];
  keepAlives: Array<string>;
} => {
  //根据菜单生成路由
  const { configs, keepAlives } = convertRouteTree(menus);

  const groups = genRouteByConfig(configs, true);

  let firstMatch = undefined;

  let i = 0;

  while (i < groups.length) {
    const { meta } = groups[i];
    if (meta?.hidden) {
      i++;
    } else {
      firstMatch = groups[i];
      break;
    }
  }

  const { redirect, path } = firstMatch!;

  const redirectRoute: RouteRecordRaw = {
    path: '/',
    redirect: redirect || path
  };

  const routes = [redirectRoute, ...groups];

  return { routes, configs, keepAlives };
};

export default genRoutes;
